package com.example.common.recycler.decoration;

import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

/**
 * 适用于item项宽度比每个span宽度小的情况
 * 最终达到的效果就是每行的第一个贴在左边，最后一个贴在右边，剩下的水平居中
 * <p>
 * itemview布局示例（注意必须要有ViewGroup,如本例的ConstraintLayout,而且此时layout_width必定为match_parent,layout_height必定为wrap_content,即使你写成其他也不会生效，如本例的layout_width="wrap_content"就是无效的，到了这里，我猜测google就是用viewstub实现的）：
 * <?xml version="1.0" encoding="utf-8"?>
 * <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 * xmlns:app="http://schemas.android.com/apk/res-auto"
 * android:layout_width="wrap_content"
 * android:layout_height="wrap_content"
 * <p>
 * <ImageView
 * android:layout_width="32dp"
 * android:layout_height="32dp"
 * android:src="@drawable/emoji1"
 * app:layout_constraintStart_toStartOf="parent"
 * app:layout_constraintTop_toTopOf="parent" />
 * <p>
 * </androidx.constraintlayout.widget.ConstraintLayout>
 */
public class GridWrapItemDecoration extends RecyclerView.ItemDecoration {
    private int mSpanCount;//列数
    private int mVerticalSpace;//垂直间隔，px
    private int mItemWidth;//itemview实际展示的宽度

    /**
     * 垂直间隔与计算得到水平间隔一致
     *
     * @param spanCount 列数
     */
    public GridWrapItemDecoration(int spanCount) {
        this.mSpanCount = spanCount;
    }

    /**
     * 用户自定义垂直间隔
     *
     * @param spanCount     列数
     * @param verticalSpace 垂直间隔，px
     */
    public GridWrapItemDecoration(int spanCount, int verticalSpace) {
        this(spanCount);
        this.mVerticalSpace = verticalSpace;
    }

    /**
     * 垂直间隔
     *
     * @param verticalSpace px
     */
    public void setVerticalSpace(int verticalSpace) {
        this.mVerticalSpace = verticalSpace;
    }

    /**
     * 网格的列数
     *
     * @param spanCount
     */
    public void setSpanCount(int spanCount) {
        this.mSpanCount = spanCount;
    }

    @Override
    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        if (!(view instanceof ViewGroup && ((ViewGroup) view).getChildCount() == 1)) {
            return;
        }
        super.getItemOffsets(outRect, view, parent, state);

        int recyclerViewWidth = getRestMeasureWidth(parent);
        int spanWidth = recyclerViewWidth / mSpanCount;
        int verticalSpace = mVerticalSpace <= 0 ? (recyclerViewWidth - mItemWidth * mSpanCount) / (mSpanCount - 1) : mVerticalSpace;//垂直间隔,优先使用用户设置的间隔

        if (mItemWidth <= 0) {
            View child = ((ViewGroup) view).getChildAt(0);
            measure(child, spanWidth, getRestMeasureHeight(parent));
            mItemWidth = child.getMeasuredWidth();
        }
//        Log.i("123456", "recyclerViewWidth=" + recyclerViewWidth + ",spanWidth=" + spanWidth + ",itemWidth=" + mItemWidth + ",verticalSpace=" + verticalSpace);

        int pos = parent.getChildAdapterPosition(view);
        if (pos > mSpanCount - 1) {
            outRect.top = verticalSpace;
        }

        int spanRestWidth = spanWidth - mItemWidth;
        int posPerRow = pos % mSpanCount;//在每一行的位置，即[0,mSpanCount-1]
        if (posPerRow == 0) {
            outRect.left = 0;
        } else if (posPerRow == mSpanCount - 1) {
            outRect.left = spanRestWidth;//将最后一个移到最右边
        } else {
            outRect.left = posPerRow * spanRestWidth / (mSpanCount - 1);//将最后一个移到最右边后多出的宽度平摊给其他
        }
    }

    /**
     * 对view进行测量
     *
     * @param view
     * @param restWidth  view的父剩余宽度
     * @param restHeight view的父剩余高度
     */
    public void measure(@NonNull View view, int restWidth, int restHeight) {
        int widthMeasureMode = View.MeasureSpec.EXACTLY;
        int heightMeasureMode = View.MeasureSpec.EXACTLY;
        ViewGroup.LayoutParams lp = view.getLayoutParams();
        if (lp == null) {
            view.measure(View.MeasureSpec.makeMeasureSpec(restWidth, widthMeasureMode),
                    View.MeasureSpec.makeMeasureSpec(restHeight, heightMeasureMode));
            return;
        }
        if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {//WRAP_CONTENT需要AT_MOST的测量模式
            widthMeasureMode = View.MeasureSpec.AT_MOST;
        } else if (lp.width > 0) {
            restWidth = Math.min(lp.width, restWidth);
        }
        if (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {//WRAP_CONTENT需要AT_MOST的测量模式
            heightMeasureMode = View.MeasureSpec.AT_MOST;
        } else if (lp.height > 0) {
            restHeight = Math.min(lp.height, restHeight);
        }
        view.measure(View.MeasureSpec.makeMeasureSpec(restWidth, widthMeasureMode),
                View.MeasureSpec.makeMeasureSpec(restHeight, heightMeasureMode));
    }

    /**
     * 获得指定view的剩余宽度（即可供子View的最大宽度）
     *
     * @param view 此view必须是已经测量过的，否则返回值并不准确
     * @return
     */
    public int getRestMeasureWidth(@NonNull View view) {
        return view.getMeasuredWidth() - view.getPaddingEnd() - view.getPaddingStart();
    }

    /**
     * 获得指定view的剩余高度（即可供子View的最大高度）
     *
     * @param view 此view必须是已经测量过的，否则返回值并不准确
     * @return
     */
    public int getRestMeasureHeight(@NonNull View view) {
        return view.getMeasuredHeight() - view.getPaddingTop() - view.getPaddingBottom();
    }
}
